package cn.iocoder.yudao.module.system.framework.web;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.config.UserActivityProperties;
import cn.iocoder.yudao.module.system.service.useractivity.UserActivityRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户活动记录拦截器
 * 
 * @author 系统开发团队
 */
@Slf4j
public class UserActivityInterceptor implements HandlerInterceptor {

    private final UserActivityProperties userActivityProperties;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Resource
    private UserActivityRecordService userActivityRecordService;

    public UserActivityInterceptor(UserActivityProperties userActivityProperties) {
        this.userActivityProperties = userActivityProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查是否启用用户活动记录
        if (!userActivityProperties.getEnable()) {
            return true;
        }

        // 检查是否需要跳过记录
        if (shouldSkipRecording(request)) {
            return true;
        }

        // 获取当前登录用户
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return true;
        }

        try {
            String requestUri = request.getRequestURI();
            String method = request.getMethod();
            String clientIp = ServletUtils.getClientIP(request);
            String userAgent = request.getHeader("User-Agent");

            // 记录页面访问活动
            if (isRecordTypeEnabled("page_view") && "GET".equalsIgnoreCase(method)) {
                userActivityRecordService.recordPageViewActivity(
                    loginUser.getId(),
                    getUsernameFromLoginUser(loginUser),
                    loginUser.getUserType(),
                    requestUri,
                    clientIp,
                    userAgent,
                    null
                );
            }

            // 记录API调用活动
            if (isRecordTypeEnabled("api_call")) {
                userActivityRecordService.recordApiCallActivity(
                    loginUser.getId(),
                    getUsernameFromLoginUser(loginUser),
                    loginUser.getUserType(),
                    requestUri,
                    method,
                    clientIp,
                    userAgent,
                    null
                );
            }

        } catch (Exception e) {
            log.error("[UserActivityInterceptor] 记录用户活动失败", e);
        }

        return true;
    }

    /**
     * 判断是否应该跳过记录
     */
    private boolean shouldSkipRecording(HttpServletRequest request) {
        String requestUri = request.getRequestURI();

        // 检查是否为静态资源
        if (isStaticResource(requestUri)) {
            return true;
        }

        // 检查是否在排除路径中
        for (String excludePath : userActivityProperties.getExcludePaths()) {
            if (pathMatcher.match(excludePath, requestUri)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否为静态资源
     */
    private boolean isStaticResource(String requestUri) {
        if (StrUtil.isBlank(requestUri)) {
            return false;
        }

        // 检查文件扩展名
        for (String extension : userActivityProperties.getExcludeExtensions()) {
            if (requestUri.toLowerCase().endsWith(extension)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否启用指定的记录类型
     */
    private boolean isRecordTypeEnabled(String recordType) {
        return userActivityProperties.getRecordTypes().contains(recordType);
    }

    /**
     * 从LoginUser中获取用户名
     */
    private String getUsernameFromLoginUser(LoginUser loginUser) {
        if (loginUser.getInfo() != null && loginUser.getInfo().containsKey(LoginUser.INFO_KEY_NICKNAME)) {
            return loginUser.getInfo().get(LoginUser.INFO_KEY_NICKNAME);
        }
        return String.valueOf(loginUser.getId());
    }
}